package com.hx.miniblog.util.utils;

import com.hx.miniblog.exception.MiniBlogException;
import com.hx.miniblog.util.constant.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import io.vavr.control.Try;

/**
 * @author wenhao hu
 * @title: WebSocketUtil
 * @projectName miniBlog
 * @description: TODO
 * @date 2021/12/2914:21
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocketUtil {

    /**
     * 与某个客户端的连接对话，需要通过它来给客户端发送消息
     */
    private Session session;
    /**
     * 标识当前连接客户端的用户名
     */
    private String userId;


    /**
     * 用于存所有的连接服务的客户端，这个对象存储是安全的
     */
    private static ConcurrentHashMap<String, WebSocketUtil> webSocketSet = new ConcurrentHashMap<>();

    @OnOpen
    public void OnOpen(Session session, @PathParam(value = "userId") String userId) {
        this.session = session;
        this.userId = userId;
        webSocketSet.put(userId, this);
        log.info("[WebSocket] 连接成功，当前连接人数为：={}", webSocketSet.size());
    }

    @OnClose
    public void OnClose() {
        webSocketSet.remove(this.userId);
        log.info("[WebSocket] 退出成功，当前连接人数为：={}", webSocketSet.size());
    }

    @OnMessage
    public void OnMessage(String message) {
        log.info("[WebSocket] 收到消息：{}", message);
    }

    /**
     * 指定发送
     *
     * @param userId
     * @param message
     */
    public void AppointSending(String userId, String message) {
        try {
            if (checkUserOnline(userId)) {
                webSocketSet.get(userId).session.getBasicRemote().sendText(message);
            }
            log.debug(Constant.MESSAGE.USER_IS_UN_ONLINE);
        } catch (Exception e) {
            throw new MiniBlogException(Constant.MESSAGE.USER_IS_UN_ONLINE);
        }
    }

    public Boolean checkUserOnline(String userId) {
        return Try.of(() -> Objects.nonNull(webSocketSet.get(userId)))
                .getOrElseThrow((e) -> {
                    throw new MiniBlogException(Constant.MESSAGE.NET_ERROR_MESSAGE);
                });
    }

    /**
     * 群发消息
     * @param message
     */
    public void sendAll(String message) {
        webSocketSet.forEach((k, v) -> {
            try {
                v.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
    /**
     * @description todo 群发自己的id
     */
    public void sendAll() {
        webSocketSet.forEach((k, v) -> {
            try {
                v.session.getBasicRemote().sendText(k);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}
